package org.ifi.xechecs.ai;

import org.ifi.xechecs.board.Board;
import org.ifi.xechecs.board.Move;
import org.ifi.xechecs.board.Piece;
import org.ifi.xechecs.transtable.TranspositionTable;

public class Evaluator {
	Board board;
	
	//evaluate a state of board
	public static int evaluate(Board b){

//		if(TranspositionTable.exists(b.getHash())){
//			return TranspositionTable.getScore(b.getHash());
//		}
		
		int value = 0;
		int figur = 0;
		//Get 
		for (int row = 0; row < Board.LENGTH; row++) {
			for (int col = 0; col < Board.LENGTH; col++) {
				if (b.getPiece(row, col) == Piece.NONE){
					continue;
				}
				
				switch (b.getPiece(row, col)) {
				//King
				case Piece.WK:
				case Piece.BK:	
					figur = K;
					break;
				//Queen
				case Piece.WQ:
				case Piece.BQ:	
					figur = Q;
					break;
				//Bishops
				case Piece.WB:
				case Piece.BB:	
					figur = B;
					break;
				//Knight
				case Piece.WN:
				case Piece.BN:	
					figur = N;
					break;
				//Rook
				case Piece.WR:
				case Piece.BR:	
					figur = R;
					break;
				//Pawn
				case Piece.WP:
				case Piece.BP:	
					figur = P;
					break;	
				default:
					figur = 0;
					break;
				}
				
				//get index in the array of postion value
				byte indexPos = (byte)(row * 8 + col);
				int pieceIndex = getPosPiece(b.getPiece(row, col));
				if (b.getColor(indexPos) == Piece.WHITE) {
					// position score
					figur += piecePositionalScore[0][pieceIndex][indexPos];
					value += figur;
				} else {
					// figur += posvalues[row * 8 + col]; //[row][col];
					figur += piecePositionalScore[1][pieceIndex][indexPos];
					value -= figur;
				}
			}
		}

//		TranspositionTable.store(b.getHash(), (byte)0, value, (byte)0, (byte)0);
				
		return value;	
	}
	
	//use for evaluation
	public static int getPosPiece(byte piece) {
		int pieceIndex;
		// pawnWPositionalScore 0, knightPositionalScore 1, bishopPositionalScore 2,
		// rookWPositionalScore 3, queenPositionalScore 4, kingWPositionalScore 5
		switch (piece) {
		// Pawn
		case Piece.WP:
		case Piece.BP:
			pieceIndex = 0;
			break;
		// Knight
		case Piece.WN:
		case Piece.BN:
			pieceIndex = 1;
			break;
		// Bishops
		case Piece.WB:
		case Piece.BB:
			pieceIndex = 2;
			break;
		// Rook
		case Piece.WR:
		case Piece.BR:
			pieceIndex = 3;
			break;
		// Queen
		case Piece.WQ:
		case Piece.BQ:
			pieceIndex = 4;
			break;
		// King
		case Piece.WK:
		case Piece.BK:
			pieceIndex = 5;
			break;
		default:
			pieceIndex = -1;
			break;
		}
		return pieceIndex;
	}

	public void evaluateMove(Move mv){
	}
	// get and setter
	public Board getBoard() {
		return board;
	}

	public void setBoard(Board board) {
		this.board = board;
	}
	
	private static final int K = 20000;//king
	private static final int Q = 900;
	private static final int R = 500;
	private static final int B = 330;//bishop
	private static final int N = 320;
	private static final int P = 100;	
	// board for evaluate postion
	public static final int[] pawnWPositionalScore = {
         0,  0,  0,  0,  0,  0,  0,  0,
         5, 10, 10,-20,-20, 10, 10,  5,
         5, -5,-10,  0,  0,-10, -5,  5,
         0,  0,  0, 20, 20,  0,  0,  0,
         5,  5, 10, 25, 25, 10,  5,  5,
         10, 10, 20, 30, 30, 20, 10, 10,
         50, 50, 50, 50, 50, 50, 50, 50,
         0,  0,  0,  0,  0,  0,  0,  0
    };
    public static final int[] pawnBPositionalScore = {
        0,  0,  0,  0,  0,  0,  0,  0,
        50, 50, 50, 50, 50, 50, 50, 50,
        10, 10, 20, 30, 30, 20, 10, 10,
        5,  5, 10, 25, 25, 10,  5,  5,
        0,  0,  0, 20, 20,  0,  0,  0,
        5, -5,-10,  0,  0,-10, -5,  5,
        5, 10, 10,-20,-20, 10, 10,  5,
        0,  0,  0,  0,  0,  0,  0,  0
    };
    
    public static final int[] knightPositionalScore = {
    	-50,-40,-30,-30,-30,-30,-40,-50,
    	-40,-20,  0,  0,  0,  0,-20,-40,
    	-30,  0, 10, 15, 15, 10,  0,-30,
    	-30,  5, 15, 20, 20, 15,  5,-30,
    	-30,  0, 15, 20, 20, 15,  0,-30,
    	-30,  5, 10, 15, 15, 10,  5,-30,
    	-40,-20,  0,  5,  5,  0,-20,-40,
    	-50,-40,-30,-30,-30,-30,-40,-50,
    };
    
    public static final int[] bishopWPositionalScore = {
    	-20,-10,-10,-10,-10,-10,-10,-20,
    	-10,  5,  0,  0,  0,  0,  5,-10,
    	-10, 10, 10, 10, 10, 10, 10,-10,
    	-10,  0, 10, 10, 10, 10,  0,-10,
    	-10,  5,  5, 10, 10,  5,  5,-10,
    	-10,  0,  5, 10, 10,  5,  0,-10,
    	-10,  0,  0,  0,  0,  0,  0,-10,
    	-20,-10,-10,-10,-10,-10,-10,-20,
    };
    public static final int[] bishopBPositionalScore = {
    	-20,-10,-10,-10,-10,-10,-10,-20,
    	-10,  0,  0,  0,  0,  0,  0,-10,
    	-10,  0,  5, 10, 10,  5,  0,-10,
    	-10,  5,  5, 10, 10,  5,  5,-10,
    	-10,  0, 10, 10, 10, 10,  0,-10,
    	-10, 10, 10, 10, 10, 10, 10,-10,
    	-10,  5,  0,  0,  0,  0,  5,-10,
    	-20,-10,-10,-10,-10,-10,-10,-20,
    };
    
    public static final int[] rookWPositionalScore = {
		 0,  0,  0,  5,  5,  0,  0,  0,
		-5,  0,  0,  0,  0,  0,  0, -5,
		-5,  0,  0,  0,  0,  0,  0, -5,
		-5,  0,  0,  0,  0,  0,  0, -5,
		-5,  0,  0,  0,  0,  0,  0, -5,
		-5,  0,  0,  0,  0,  0,  0, -5,
		 5, 10, 10, 10, 10, 10, 10,  5,
	 	 0,  0,  0,  0,  0,  0,  0,  0,
   };
    
    public static final int[] rookBPositionalScore = {
    	  0,  0,  0,  0,  0,  0,  0,  0,
    	  5, 10, 10, 10, 10, 10, 10,  5,
    	 -5,  0,  0,  0,  0,  0,  0, -5,
    	 -5,  0,  0,  0,  0,  0,  0, -5,
    	 -5,  0,  0,  0,  0,  0,  0, -5,
    	 -5,  0,  0,  0,  0,  0,  0, -5,
    	 -5,  0,  0,  0,  0,  0,  0, -5,
    	  0,  0,  0,  5,  5,  0,  0,  0
    };
   
    public static final int[] queenPositionalScore = {
    	-20,-10,-10, -5, -5,-10,-10,-20,
    	-10,  0,  0,  0,  0,  0,  0,-10,
    	-10,  0,  5,  5,  5,  5,  0,-10,
    	 -5,  0,  5,  5,  5,  5,  0, -5,
    	  0,  0,  5,  5,  5,  5,  0, -5,
    	-10,  5,  5,  5,  5,  5,  0,-10,
    	-10,  0,  5,  0,  0,  0,  0,-10,
    	-20,-10,-10, -5, -5,-10,-10,-20
    };
    
    public static final int[] kingWPositionalScore = { // Middlegame only
        20, 30, 10,  0,  0, 10, 30, 20,
        20, 20,  0,  0,  0,  0, 20, 20,
       -10,-20,-20,-20,-20,-20,-20,-10,
       -20,-30,-30,-40,-40,-30,-30,-20,
       -30,-40,-40,-50,-50,-40,-40,-30,
       -30,-40,-40,-50,-50,-40,-40,-30,
       -30,-40,-40,-50,-50,-40,-40,-30,
       -30,-40,-40,-50,-50,-40,-40,-30
   };
   public static final int[] kingBPositionalScore = { // Middlegame only
	   -30,-40,-40,-50,-50,-40,-40,-30,
	   -30,-40,-40,-50,-50,-40,-40,-30,
	   -30,-40,-40,-50,-50,-40,-40,-30,
	   -30,-40,-40,-50,-50,-40,-40,-30,
	   -20,-30,-30,-40,-40,-30,-30,-20,
	   -10,-20,-20,-20,-20,-20,-20,-10,
	    20, 20,  0,  0,  0,  0, 20, 20,
	    20, 30, 10,  0,  0, 10, 30, 20
    };
   
    public static final int[] kingBEndgameScore = { // Endgame only
        -50,-40,-30,-20,-20,-30,-40,-50,
        -30,-20,-10,  0,  0,-10,-20,-30,
        -30,-10, 20, 30, 30, 20,-10,-30,
        -30,-10, 30, 40, 40, 30,-10,-30,
        -30,-10, 30, 40, 40, 30,-10,-30,
        -30,-10, 20, 30, 30, 20,-10,-30,
        -30,-30,  0,  0,  0,-30,-30,-30,
        -50,-30,-30,-30,-30,-30,-30,-50
    };
    public static final int[] kingWEndgameScore = { // Endgame only
        -50,-30,-30,-30,-30,-30,-30,-50,
        -30,-30,  0,  0,  0,-30,-30,-30,
        -30,-10, 20, 30, 30, 20,-10,-30,
        -30,-10, 30, 40, 40, 30,-10,-30,
        -30,-10, 30, 40, 40, 30,-10,-30,
        -30,-10, 20, 30, 30, 20,-10,-30,
        -30,-20,-10,  0,  0,-10,-20,-30,
        -50,-40,-30,-20,-20,-30,-40,-50
    };
    // Following array should be accessed like [Color][Piece][Position]
    public static final int[][][] piecePositionalScore = {
        {//White
            pawnWPositionalScore, knightPositionalScore, bishopWPositionalScore,
            rookWPositionalScore, queenPositionalScore, kingWPositionalScore
        },
        {
            pawnBPositionalScore, knightPositionalScore, bishopBPositionalScore,
            rookBPositionalScore, queenPositionalScore, kingBPositionalScore
        }
    };
	
}
